<?php
namespace Swiftx\Component\Router;
use Swiftx\Interfaces\Ioc\Container;
use Swiftx\Interfaces\Router\Annotation;
use Swiftx\Interfaces\Router\Collection as CollectionInterface;
use Swiftx\Interfaces\Router\Dispatcher;
use Swiftx\Interfaces\Router\Request;
use Swiftx\Interfaces\Router\Response;


/**
 * 控制器方法适配器
 *
 * @author		胡永强  <odaytudio@gmail.com>
 * @since		2015-10-09
 * @copyright	Copyright (c) 2014-2015 Swiftx Inc.
 */
class Collection implements CollectionInterface{

    /**
     * 依赖注入容器
     * @var Container
     */
    protected $container = null;

    /**
     * 路由适配器
     * @var Dispatcher[]
     */
    protected $dispatchers = [];

    /**
     * 注入依赖容器
     * @param Container $container
     * @auto-injection
     */
    public function setContainer(Container $container){
        $this->container = $container;
    }

    /**
     * 注册一个路由器映射
     *
     * @param string $name
     * @param Dispatcher $dispatcher
     * @return mixed|void
     */
    public function registerDispatcher(string $name, Dispatcher $dispatcher){
        $this->dispatchers[$name] = $dispatcher;
    }

    /**
     * 注解解析接口或类
     * @param string $value
     * @param string[] $evn
     * @throws \ErrorException
     */
    public function parseAnnotation(string $value, array $evn = []){
        $class = new \ReflectionClass($value);
        $document = $class->getDocComment();
        $params = [];
        if(!preg_match('/@router-annotation\s+(\S+)+\s+/', $document, $params))
            throw new \ErrorException('路由接口：'.$value.' 未指定注解解析器');
        /** @var Annotation $annotation */
        $annotation = $this->container->fetch($params[1]);
        $annotation->setReflection($class);
        $annotation->parser($this, $evn);
    }

    /**
     * 执行路由分发
     * @param Request $request
     * @param Response $response
     * @return void
     */
    public function dispatch(Request $request, Response $response){
        foreach($this->dispatchers as $dispatcher){
            if(!$dispatcher->pattern($request)) continue;
            $dispatcher->bundle($request, $response); return;
        }
        throw new DispatcherNoFound('路由器未找到');
    }

    /**
     * 获取路由器分发器
     * @param string $name
     * @param string $action
     * @return Dispatcher
     */
    public function getDispatcher(string $name, string $action):Dispatcher{
        return $this->dispatchers[$name.'::'.$action];
    }

    /**
     * 获取所有路由器分发器
     * @return Dispatcher[]
     */
    public function getDispatchers():array {
        return $this->dispatchers;
    }

}